package com.corpgovernment.common.aspect;

import com.alibaba.fastjson.JSONObject;
import com.corpgovernment.common.common.ContextUtils;
import com.corpgovernment.common.entity.Constan;
import com.corpgovernment.common.entity.LogToken;
import com.corpgovernment.common.enums.ExceptionCodeEnum;
import com.corpgovernment.common.enums.LogLevelEnum;
import com.corpgovernment.common.logging.LogUtil;
import com.ctrip.corp.obt.generic.core.http.HttpResponse;
import com.ctrip.corp.obt.generic.exception.CommonException;
import com.ctrip.corp.obt.generic.utils.EnvironmentHolder;
import com.ctrip.corp.obt.metric.Metrics;
import com.ctrip.corp.obt.metric.spectator.api.Id;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @program: corpgovernment-common-logging
 * @description: controller全局异常处理
 * @author: wubing
 * @create: 2019-06-13 10:15
 */
@Order(-500)
@ControllerAdvice(annotations = RestController.class)
@ResponseBody
@Slf4j
public class ExceptionAdvice {
    Id unHandleExceptionId = Metrics.REGISTRY.createId("common.aspect.unHandleException");
    @ExceptionHandler(value = Exception.class)
    public Object errorHandler(Exception ex, HttpServletRequest request) {
        JSONObject json = new JSONObject();
        String msg = "";
        if (ex instanceof MethodArgumentNotValidException) {
            BindingResult result = ((MethodArgumentNotValidException) ex).getBindingResult();
            List<ObjectError> allErrors = result.getAllErrors();
            List<String> errorList = allErrors.stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.toList());
            json.put("status", ExceptionCodeEnum.Alert.getValue());
            json.put("msg", String.join(",", errorList));
            return json;
        }
        json.put("status", ExceptionCodeEnum.Alert.getValue());
        msg = "服务器忙，请稍后重试";
        json.put("msg", msg);
        //log.warn(request.getRequestURI() + ", msg:{}", msg, ex);
        Map<String, String> tagMaps = new HashMap<>(16);
        tagMaps.put("uri", request.getRequestURI());
        LogToken logToken = (LogToken) ContextUtils.INSTANCE.get();
        if (logToken != null) {
            tagMaps.put("token", StringUtils.isEmpty(logToken.getToken()) ? logToken.getToken() : logToken.getHeaderToken());
            tagMaps.put(Constan.request_id, logToken.getRequestId());
        }
        LogUtil.logging(LogLevelEnum.Error, ExceptionAdvice.class, "系统异常", LogUtil.getException(ex), tagMaps);
        recordMetric();
        HttpHeaders headers = new HttpHeaders();
        // system exception 1101
        headers.set("X-RC", "1101");
        headers.setContentType(MediaType.APPLICATION_JSON);
        return new ResponseEntity<>(json, headers,
                HttpStatus.OK);
    }

    private void recordMetric(){
        Map<String, String> tags = new HashMap<>();
        tags.put("application", EnvironmentHolder.getApplicationName());
        Metrics.REGISTRY.counter(unHandleExceptionId.withTags(tags)).increment();

    }
}